package com.kcloud.commons.authorization.mp.parser;

import com.baomidou.mybatisplus.core.parser.AbstractJsqlParser;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;

import com.kcloud.commons.authorization.annotation.Authorization;
import com.kcloud.commons.authorization.mp.handler.column.IAttributeAuthorizationHandler;
import lombok.Getter;
import lombok.Setter;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.update.Update;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.reflection.MetaObject;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.List;

/**
 * 权限表字段解析
 * @author songhuiqing
 */
public class AttributeAuthorizationParser extends AbstractJsqlParser {

    @Getter
    @Setter
    private List<IAttributeAuthorizationHandler> tableColumnHandlers;
    @Override
    public void processInsert(Insert insert) {
        //那些列可以插入
    }

    @Override
    public void processDelete(Delete delete) {
        //删除在属性权限是，不需要控制
    }

    @Override
    public void processUpdate(Update update) {
        //那些列可以更行
    }

    @Override
    public void processSelectBody(SelectBody selectBody) {
        //那些列可以查询
    }

    @Override
    public boolean doFilter(MetaObject metaObject, String sql) {
        MappedStatement mappedStatement = getMappedStatement(metaObject);
        String id = mappedStatement.getId();
        try {
            Class<?> entityClass = extractModelClass(Class.forName(id.substring(0, id.lastIndexOf("."))));
            Authorization authAnnotation = entityClass.getDeclaredAnnotation(Authorization.class);
            if(authAnnotation != null && tableColumnHandlers != null && tableColumnHandlers.size() != 0) {
                return true;
            }
        } catch (ClassNotFoundException e) {

        }
        return false;
    }


    /**
     * 提取泛型模型,多泛型的时候请将泛型T放在第一位
     *
     * @param mapperClass mapper 接口
     * @return mapper 泛型
     */
    private Class<?> extractModelClass(Class<?> mapperClass) {
        Type[] types = mapperClass.getGenericInterfaces();
        ParameterizedType target = null;
        for (Type type : types) {
            if (type instanceof ParameterizedType) {
                Type[] typeArray = ((ParameterizedType) type).getActualTypeArguments();
                if (ArrayUtils.isNotEmpty(typeArray)) {
                    for (Type t : typeArray) {
                        if (t instanceof TypeVariable || t instanceof WildcardType) {
                            break;
                        } else {
                            target = (ParameterizedType) type;
                            break;
                        }
                    }
                }
                break;
            }
        }
        return target == null ? null : (Class<?>) target.getActualTypeArguments()[0];
    }
    private MappedStatement getMappedStatement(MetaObject metaObject) {
        return (MappedStatement) metaObject.getValue("delegate.mappedStatement");
    }
}
